#include "SymbolTable.h"
#include <iostream>

namespace MiniDB {

bool SymbolTable::addTable(const TableInfo& table) {
    if (hasTable(table.name)) {
        std::cerr << "Error: Table '" << table.name << "' already exists" << std::endl;
        return false;
    }

    tables_[table.name] = table;
    return true;
}

bool SymbolTable::hasTable(const std::string& table_name) const {
    return tables_.find(table_name) != tables_.end();
}

const TableInfo* SymbolTable::getTable(const std::string& table_name) const {
    auto it = tables_.find(table_name);
    if (it != tables_.end()) {
        return &it->second;
    }
    return nullptr;
}

std::vector<std::string> SymbolTable::getTableNames() const {
    std::vector<std::string> names;
    names.reserve(tables_.size());
    for (const auto& pair : tables_) {
        names.push_back(pair.first);
    }
    return names;
}

bool SymbolTable::hasColumn(const std::string& table_name, const std::string& column_name) const {
    const TableInfo* table = getTable(table_name);
    if (!table) return false;

    return table->hasColumn(column_name);
}

const ColumnInfo* SymbolTable::getColumn(const std::string& table_name, const std::string& column_name) const {
    const TableInfo* table = getTable(table_name);
    if (!table) return nullptr;

    return table->getColumn(column_name);
}

bool SymbolTable::areTypesCompatible(DataType type1, DataType type2) const {
    // Same types are always compatible
    if (type1 == type2) return true;

    // INT and FLOAT are compatible
    if ((type1 == DataType::INT && type2 == DataType::FLOAT) ||
        (type1 == DataType::FLOAT && type2 == DataType::INT)) {
        return true;
    }

    // VARCHAR and TEXT are compatible
    if ((type1 == DataType::VARCHAR && type2 == DataType::TEXT) ||
        (type1 == DataType::TEXT && type2 == DataType::VARCHAR)) {
        return true;
    }

    return false;
}

DataType SymbolTable::getResultType(DataType type1, DataType type2) const {
    // Same types
    if (type1 == type2) return type1;

    // INT and FLOAT -> FLOAT
    if ((type1 == DataType::INT && type2 == DataType::FLOAT) ||
        (type1 == DataType::FLOAT && type2 == DataType::INT)) {
        return DataType::FLOAT;
    }

    // VARCHAR and TEXT -> TEXT
    if ((type1 == DataType::VARCHAR && type2 == DataType::TEXT) ||
        (type1 == DataType::TEXT && type2 == DataType::VARCHAR)) {
        return DataType::TEXT;
    }

    // Default to first type
    return type1;
}

void SymbolTable::clear() {
    tables_.clear();
}

} // namespace MiniDB
